using System;
using System.Collections.Generic;
using System.Text;

namespace Zsa.Emulation.Processor
{
    /// <summary>
    /// Static data related to a 
    /// </summary>
    public struct OpCode
    {


        //public static byte GetInstructionSize(OpCodes code)
        //{
        //    byte _Op = (byte)_OpCode;
        //    _Op &= (byte)MemoryAddressingType.AllBits;
        //    MemoryAddressingType _MemType = (MemoryAddressingType)_Op;
        //    if ( _MemType == MemoryAddressingType.Absolute || _MemType == MemoryAddressingType.

        //}

        /// <summary>
        /// Gets the empty.
        /// </summary>
        /// <value>The empty.</value>
        public static OpCode Empty
        {
            get
            {
                return new OpCode();
            }
        }

        /// <summary>
        /// Overloaded equality operator.
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns></returns>
        public static bool operator ==(OpCode x, OpCode y)
        {
            return x._OpCode == y._OpCode && x._Cycles == y._Cycles &&
                x._Size == y._Size;
        }

        /// <summary>
        /// Overloaded inequality operator
        /// </summary>
        /// <param name="x">The x.</param>
        /// <param name="y">The y.</param>
        /// <returns></returns>
        public static bool operator !=(OpCode x, OpCode y)
        {
            return x._OpCode != y._OpCode || x._Cycles != y._Cycles ||
                x._Size != y._Size;
        }



        #region Fields
        /// <summary>
        /// The op code.
        /// </summary>
        private readonly OpCodes _OpCode;

        /// <summary>
        /// The size of the opcodes data.
        /// </summary>
        private readonly byte _Size;

        /// <summary>
        /// The number of cycles the op code uses.
        /// </summary>
        private readonly byte _Cycles;

        #endregion Fields

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="T:OpCode"/> class.
        /// </summary>
        /// <param name="code">The code.</param>
        /// <param name="size">The size.</param>
        /// <param name="cycles">The cycles.</param>
        public OpCode(OpCodes code, byte size, byte cycles)
        {
            _OpCode = code;
            _Size = size;
            _Cycles = cycles;
        }
        #endregion Constructor

        #region Properties

        /// <summary>
        /// Gets the instruction.
        /// </summary>
        /// <value>The instruction.</value>
        public OpCodes Instruction
        {
            get
            {
                return _OpCode;
            }
        }
        /// <summary>
        /// Gets the type of the address.
        /// </summary>
        /// <value>The type of the address.</value>
        public MemoryAddressingType AddressType
        {
            get
            {
                byte _Op = (byte)_OpCode;
                _Op &= (byte)MemoryAddressingType.AllBits;
                return (MemoryAddressingType)_Op;
            }
        }

        /// <summary>
        /// Gets the size of the instruction.
        /// </summary>
        /// <value>The size of the instruction.</value>
        public byte InstructionSize
        {
            get
            {
                return _Size;
            }
        }

        /// <summary>
        /// Gets the cycles.
        /// </summary>
        /// <value>The cycles.</value>
        public byte Cycles
        {
            get
            {
                return _Cycles;
            }
        }
        #endregion Properties

        #region Methods
        /// <summary>
        /// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
        /// </returns>
        public override string ToString()
        {
            return string.Format(
                "{0}-{1:X2} T:{2} L:{3} M:{4}",
                _OpCode.ToString(),
                (int)_OpCode,
                _Cycles,
                _Size,
                AddressType.ToString()
            );
        }
        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>.
        /// </summary>
        /// <param name="obj">The <see cref="T:System.Object"></see> to compare with the current <see cref="T:System.Object"></see>.</param>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>; otherwise, false.
        /// </returns>
        public override bool Equals(object obj)
        {
            if (!( obj is OpCode))
            {
                return false;
            }
            OpCode _Code = (OpCode)obj;
            return _Code == this;
        }

        /// <summary>
        /// Returns the hash code for this instance.
        /// </summary>
        /// <returns>
        /// A 32-bit signed integer that is the hash code for this instance.
        /// </returns>
        public override int GetHashCode()
        {
            return _OpCode.GetHashCode();
        }
        #endregion Methods

    }
}
